package connect

import (
	"encoding/json"
	"errors"
	"litetalk/db"
	"litetalk/proto"

	"github.com/sirupsen/logrus"
)

func Push(p *proto.Msg) error {
	var (
		b   *Bucket
		c   *Channel
		err error
	)

	if p.Op != proto.OpSingleSend {
		return errors.New("not support operation")
	}

	imMessage := &proto.IMMessage{}
	err = json.Unmarshal(p.Msg, imMessage)
	if err != nil {
		logrus.Errorln("connect Push json.Unmarshal ", err)
		return err
	}

	// 0 把消息保存到数据库
	imMessage.MsgId = db.Message.Add(imMessage.FromUserId, imMessage.SessionId, imMessage.MsgData)

	// 1 通知发送者发送成功
	b = DefaultServer.Bucket(imMessage.FromUserId)
	c = b.Channel(imMessage.FromUserId)
	if c != nil {
		ack := &proto.IMMessageAck{
			FromUserId: imMessage.FromUserId,
			SessionId:  imMessage.SessionId,
			MsgId:      imMessage.MsgId,
		}

		body, _ := json.Marshal(ack)
		pack := proto.NewMsg(proto.OpSingleSendAck, body, p.Seq)
		c.PushMsg(pack)
	}

	// 2 通知接收者接受消息
	b = DefaultServer.Bucket(imMessage.SessionId)
	c = b.Channel(imMessage.SessionId)
	if c == nil {
		// 接收者未上线
		logrus.Infof("connect Push target offline")
		return nil
	}

	p.Seq = 0
	c.PushMsg(p)
	return nil
}

func PushGroup(p *proto.Msg) (err error) {
	var (
		b *Bucket
		c *Channel
	)

	if p.Op != proto.OpGroupSend {
		err = errors.New("not support operation")
		logrus.Error(err)
		return
	}

	imMessage := &proto.IMMessage{}
	err = json.Unmarshal(p.Msg, imMessage)
	if err != nil {
		logrus.Errorln("connect Push json.Unmarshal ", err)
		return err
	}

	// 1 通知发送者发送成功
	b = DefaultServer.Bucket(imMessage.FromUserId)
	c = b.Channel(imMessage.FromUserId)
	if c != nil {
		ack := &proto.IMMessageAck{
			FromUserId: imMessage.FromUserId,
			SessionId:  imMessage.SessionId,
			MsgId:      imMessage.MsgId,
		}
		body, _ := json.Marshal(ack)
		pack := proto.NewMsg(proto.OpGroupSendAck, body, p.Seq)
		c.PushMsg(pack)
	}

	// 2 查询数据库组中的成员
	groupMember := &db.IMGroupMember{}
	members := groupMember.GetDataByGroupId(imMessage.SessionId)
	// 3 判断发送者是否在这个组中
	inGroup := false
	for _, member := range members {
		if member.UserId == imMessage.FromUserId {
			inGroup = true
		}
	}
	if !inGroup {
		err = errors.New("this user not in group")
		return
	}
	// 4 转发给所有在组中的用户
	for _, member := range members {
		c = DefaultServer.Bucket(member.UserId).Channel(member.UserId)
		c.PushMsg(p)
	}
	return nil
}

func Broadcast(p *proto.Msg, from uint) error {
	for _, bucket := range DefaultServer.Buckets {
		bucket.Broadcast(p, from)
	}
	return nil
}

func Multicast(p *proto.Msg, list []uint) error {
	for _, id := range list {
		ch := DefaultServer.Bucket(id).Channel(id)
		if ch != nil {
			ch.PushMsg(p)
		}
	}
	return nil
}
